#include <QtGui/QApplication>
#include "mainwindow.h"

#include <boost/thread.hpp>
#include <iostream>
#include <cstdio>
#include <QDebug>
#include <boost/thread/locks.hpp>


#define MAXIMO 100



using namespace std;
using namespace boost;



shared_mutex _access;
int teste;
thread * consumidores[MAXIMO];
int produtos;



void consome(int seletor)
{
    shared_lock<shared_mutex> lock(_access);
    //fazer as coisas todos acessam ao mesmo tempo
    qDebug() << "começou consumidor " << seletor << endl;

    for (int i =0; i<1000000;i++){}

    teste --;

    for (int i =0; i<1000000;i++){}


    qDebug() << "saiu consumidor " << seletor << endl;





    /*
    if (seletor == 0)
    {
        for (int i =0; i<100; i++)
        {
            qDebug() << "#" << endl;
        }
    }

    if (seletor == 1)
    {
        for (int i =0; i<10000; i++)
        {
            qDebug() << "O" << endl;
        }

    }
    */
}


void produz()
{
    unique_lock<shared_mutex> lock(_access);
    //aqui escritor escreve sozinho

    qDebug() << "parem, estou produzindo" << endl;

    for (int i =0; i<100; i++)
    {
        qDebug() << ".";
    }

    qDebug() << "podem continuar..." << endl;

    lock.release();
}





//alterar issothread *consumidores[]
void displayAndChange(thread& daThread)
{
    int retcode;
    int policy;

    pthread_t threadID = (pthread_t) daThread.native_handle();

    struct sched_param param;

    /*
    if ((retcode = pthread_getschedparam(threadID, &policy, &param)) != 0)
    {
        errno = retcode;
        perror("pthread_getschedparam");
        exit(EXIT_FAILURE);
    }
    */

    /*
    cout << "INHERITED: ";
    cout << "policy=" << ((policy == SCHED_FIFO)  ? "SCHED_FIFO" :
                               (policy == SCHED_RR)    ? "SCHED_RR" :
                               (policy == SCHED_OTHER) ? "SCHED_OTHER" :
                                                         "???")
              << ", priority=" << param.sched_priority << endl;


    */

    policy = SCHED_RR;
    param.sched_priority = 99;

    if ((retcode = pthread_setschedparam(threadID, policy, &param)) != 0)
    {
        errno = retcode;
        perror("pthread_setschedparam");
        exit(EXIT_FAILURE);
    }

    cout << "  CHANGED: ";
    cout << "policy=" << ((policy == SCHED_FIFO)  ? "SCHED_FIFO" :
                               (policy == SCHED_RR)    ? "SCHED_RR" :
                               (policy == SCHED_OTHER) ? "SCHED_OTHER" :
                                                          "???")
              << ", priority=" << param.sched_priority << endl;
}



void executaCoisas()
{
    thread_group grupoConsumidores;

    qDebug() << "bitches, I'm back!.." << endl;


    teste = MAXIMO;


    for (int i=0; i<MAXIMO; i++)
    {
        consumidores[i] = grupoConsumidores.create_thread(bind(consome, i));
    }


    ///------- COISAS PARA TROCAR PRIORIDADE-----

    int policy, res;

    struct sched_param param;

    if ((policy = sched_getscheduler(getpid())) == -1)
    {
        perror("sched_getscheduler");
        exit(EXIT_FAILURE);
    }

    if ((res = sched_getparam(getpid(), &param)) == -1)
    {
        perror("sched_getparam");
        exit(EXIT_FAILURE);
    }

    std::cout << " ORIGINAL: ";
    std::cout << "policy=" << ((policy == SCHED_FIFO)  ? "SCHED_FIFO" :
                               (policy == SCHED_RR)    ? "SCHED_RR" :
                               (policy == SCHED_OTHER) ? "SCHED_OTHER" :
                                                          "???")
              << ", priority=" << param.sched_priority << std::endl;


    //policy = SCHED_RR;
    //param.sched_priority = 2;

    //if ((res = sched_setscheduler(getpid(), policy, &param)) == -1)
    //{
     //   perror("sched_setscheduler");
      //  exit(EXIT_FAILURE);
    //}

    ///------ FIM DESSAS COISAS



    thread threadProdutor(produz);

    displayAndChange(threadProdutor);


    //thread threadConsumidor(consome, 0);
    //thread threadConsumidor2(consome, 1);

    qDebug() << "esperando o join" << endl;

    qDebug() << "valor de teste: " << teste << endl;

    threadProdutor.join();
  //  threadConsumidor2.join();
//    threadConsumidor.join();


    grupoConsumidores.join_all();


    qDebug() << "valor de teste: " << teste << endl;


}




int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    w.ptrFunc = executaCoisas;
    //w.consumidores = consumidores;
    //executaCoisas();


    return a.exec();

}
